package io.zcoder.innoway.fragments;


import android.graphics.Color;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.RelativeLayout;

import com.github.mikephil.charting.charts.LineChart;
import com.github.mikephil.charting.components.AxisBase;
import com.github.mikephil.charting.components.Legend;
import com.github.mikephil.charting.components.LimitLine;
import com.github.mikephil.charting.components.XAxis;
import com.github.mikephil.charting.data.Entry;
import com.github.mikephil.charting.data.LineData;
import com.github.mikephil.charting.data.LineDataSet;
import com.github.mikephil.charting.formatter.IAxisValueFormatter;
import com.github.mikephil.charting.interfaces.datasets.ILineDataSet;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

import butterknife.BindView;
import butterknife.BindViews;
import butterknife.ButterKnife;
import butterknife.OnClick;
import io.zcoder.innoway.R;
import io.zcoder.innoway.utils.Utils;
import io.zcoder.innoway.activities.BaseActivity;
import io.zcoder.innoway.adapters.EntryTimeAdapter;
import io.zcoder.innoway.commons.Constants;
import io.zcoder.innoway.commons.PrefUtils;
import io.zcoder.innoway.models.EntryTime;
import io.zcoder.innoway.models.EntryTimeResponse;
import io.zcoder.innoway.models.Profile;
import io.zcoder.innoway.rest.RestClient;
import io.zcoder.innoway.widgets.TextViewCustom;
import retrofit.Callback;
import retrofit.RetrofitError;
import retrofit.client.Response;

public class TrendDetailFragment extends Fragment {

    private final static String[] GROUPBY = {"day", "week", "month"};
    private final static String[] FORMAT_TIME_RESPONSE = {"yyyy-MM-dd", "yyyy-ww", "yyyy-MM"};
    private final static String[] FORMAT_TIME = {"MMM dd, yyyy", "'Week' ww-yyyy", "MMMM yyyy"};
    private final static String[] FORMAT_LABEL = {"dd/MM", "dd/MM", "dd/MM"};
    private final static int[] COUNT_LABEL = {7, 4, 12};
    private final static int[] DATE_UNIT = {Calendar.DAY_OF_MONTH, Calendar.WEEK_OF_MONTH, Calendar.MONTH};

    @BindViews({R.id.tab_text_1, R.id.tab_text_2, R.id.tab_text_3})
    TextViewCustom[] mTabText;
    @BindViews({R.id.tab_line_1, R.id.tab_line_2, R.id.tab_line_3})
    View[] mTabLine;
    @BindView(R.id.label_time)
    TextViewCustom mLabelTime;
    @BindView(R.id.label_time_title)
    TextViewCustom mLabelTimeTitle;
    @BindView(R.id.chart)
    LineChart mLineChart;
    @BindView(R.id.list_entry_time)
    RecyclerView mRecyclerView;
    @BindView(R.id.layout_goal)
    RelativeLayout mLayoutGoal;
    @BindView(R.id.avg_text)
    TextViewCustom mAvg;
    @BindView(R.id.avg_text_unit)
    TextViewCustom mAvgUnit;
    @BindView(R.id.goal_text)
    TextViewCustom mGoal;
    @BindView(R.id.goal_text_unit)
    TextViewCustom mGoalUnit;

    @OnClick(R.id.tab_text_1)
    void clickTab1() {
        if (mTabLine[0].getVisibility() == View.GONE) {
            setTab(0);
        }
    }

    @OnClick(R.id.tab_text_2)
    void clickTab2() {
        if (mTabLine[1].getVisibility() == View.GONE) {
            setTab(1);
        }
    }

    @OnClick(R.id.tab_text_3)
    void clickTab3() {
        if (mTabLine[2].getVisibility() == View.GONE) {
            setTab(2);
        }
    }

    private int mPosition;
    private int mCurrentType = -1;
    private Date mEndDate;
    private Date mStartDateDay;
    private Date mStartDate4Week;
    private Date mStartDate12Month;
    private Date mStartDateSelect;
    private List<EntryTime> mEntryTimes;
    private Profile mProfile;

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mPosition = getArguments().getInt(Constants.INDEX_EXTRAS);
        mProfile = getArguments().getParcelable(Constants.PROFILE_EXTRAS);
        Calendar calendar = Calendar.getInstance();
        mEndDate = calendar.getTime();
        calendar.add(Calendar.DAY_OF_MONTH, -6);
        mStartDateDay = calendar.getTime();
        calendar = Calendar.getInstance();
        calendar.add(Calendar.WEEK_OF_YEAR, -3);
        mStartDate4Week = calendar.getTime();
        calendar = Calendar.getInstance();
        calendar.add(Calendar.MONTH, -11);
        mStartDate12Month = calendar.getTime();

    }

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.layout_trend_detail_fragment, container, false);
        ButterKnife.bind(this, view);
        if (mPosition == 0) {
            mLayoutGoal.setVisibility(View.VISIBLE);
        }
        setTab(0);
        return view;
    }

    public void getData() {
        String type = getString(Utils.getIdEntry(mPosition)).toLowerCase();
        type = type.replace(" ", "_");
        RestClient.build(getActivity(), true).getEntryTime(PrefUtils.getInt(getActivity(), PrefUtils.PREF_PROFILE_ID),
                Utils.convertToString(mStartDateSelect, Utils.DATE_FORMAT_YYY_MM_DD),
                Utils.convertToString(mEndDate, Utils.DATE_FORMAT_YYY_MM_DD), type, GROUPBY[mCurrentType],
                new Callback<EntryTimeResponse>() {
                    @Override
                    public void success(EntryTimeResponse entryTimeResponse, Response response) {
                        if (entryTimeResponse.getStatus_code() != 200) {
                            ((BaseActivity) getActivity()).showAlert(getString(R.string.error), entryTimeResponse.getMessage());
                        } else {
                            mEntryTimes = entryTimeResponse.getData();
                            setViews();
                        }
                    }

                    @Override
                    public void failure(RetrofitError error) {
                    }
                });
    }

    private void setViews() {
        mLineChart.clear();
        if (mEntryTimes == null || mEntryTimes.size() == 0) {
            return;
        }
//        List<Entry> entries = new ArrayList<>();
//        for (int i = mEntryTimes.size() - 1; i >= 0; i--) {
//            entries.add(new Entry(convertDateToInt(mEntryTimes.get(i).getTime()),
//                    mEntryTimes.get(i).getValue(mPosition > 0 ? "%" : Utils.getUnitWeight(mProfile.getWeight_unit()))));
//        }
//        LineDataSet dataSet = new LineDataSet(entries, getString(Utils.getIdEntry(mPosition)));
//        dataSet.setColor(getResources().getColor(getIdColor(mPosition)));
//        dataSet.setFillColor(getResources().getColor(getIdColor(mPosition)));
//        dataSet.setDrawFilled(true);
//        dataSet.setDrawValues(false);
//        dataSet.setFillAlpha(200);


        List<Entry> entrySpace = new ArrayList<>();
        final Calendar calendar = Calendar.getInstance();
        calendar.add(DATE_UNIT[mCurrentType], (COUNT_LABEL[mCurrentType] - 1) * -1);
        for (int i = 0; i < COUNT_LABEL[mCurrentType]; i++) {
            float valueY = 0;
            float valueX = convertDateToInt(calendar.getTime());
            String valueXS = Utils.convertToString(calendar.getTime(), FORMAT_TIME_RESPONSE[mCurrentType]);
            for (int j = 0; j < mEntryTimes.size(); j++) {
                if (valueXS.equalsIgnoreCase(mEntryTimes.get(j).getTime())) {
                    String unit = "%";
                    if (mPosition == 0) {
                        unit = Utils.getUnitWeight(mProfile.getWeight_unit());
                    }
                    if (mPosition == 6) {
                        unit = "Kg";
                    }
                    if (mPosition == 7) {
                        unit = "Kcal";
                    }
                    valueY = mEntryTimes.get(j).getValue(unit);
                    break;
                }
            }
            entrySpace.add(new Entry(i + 1, valueY));
            calendar.add(DATE_UNIT[mCurrentType], 1);
        }
        LineDataSet dataSetSpace = new LineDataSet(entrySpace, getString(Utils.getIdEntry(mPosition)));
        dataSetSpace.setColor(getResources().getColor(getIdColor(mPosition)));
        dataSetSpace.setFillColor(getResources().getColor(getIdColor(mPosition)));
        dataSetSpace.setDrawFilled(true);
        dataSetSpace.setDrawValues(false);
        dataSetSpace.setFillAlpha(200);

        List<ILineDataSet> lineDataSets = new ArrayList<>();
        lineDataSets.add(dataSetSpace);
//        lineDataSets.add(dataSet);
        if (mPosition == 0) {
            List<Entry> entry1 = new ArrayList<>();
            entry1.add(new Entry(1, mProfile.getGoalWeight(mProfile.getWeight_unit())));
            LineDataSet dataSetGoal = new LineDataSet(entry1, getString(R.string.goal));
            dataSetGoal.setColor(Color.RED);
            dataSetGoal.setDrawValues(false);
            dataSetGoal.enableDashedLine(10, 10, 1);
            dataSetGoal.setDrawCircles(false);
            lineDataSets.add(dataSetGoal);
        }

        LineData lineData = new LineData(lineDataSets);
        mLineChart.setData(lineData);

        LimitLine limitLine = new LimitLine(mProfile.getGoalWeight(mProfile.getWeight_unit()));
        limitLine.setLabel("");
        limitLine.setLineColor(Color.RED);
        limitLine.enableDashedLine(10, 10, 1);
        if (mPosition == 0) {
            mLineChart.getAxisRight().addLimitLine(limitLine);
        }

        mLineChart.getAxisLeft().setDrawGridLines(false);
        mLineChart.getAxisLeft().setTextColor(Color.WHITE);
        mLineChart.getAxisLeft().setSpaceBottom(0);
        mLineChart.getAxisLeft().setDrawAxisLine(false);
        mLineChart.getAxisLeft().setValueFormatter(new MyValueFormatter());
        mLineChart.getAxisLeft().setAxisMinimum(0);

        mLineChart.getAxisRight().setDrawGridLines(false);
        mLineChart.getAxisRight().setEnabled(false);

        mLineChart.getXAxis().setEnabled(true);
        mLineChart.getXAxis().setDrawGridLines(false);
        mLineChart.getXAxis().setYOffset(15);
        mLineChart.getXAxis().setCenterAxisLabels(false);
        if (mCurrentType == 2) {
            mLineChart.getXAxis().setLabelRotationAngle(-90);
        }
        mLineChart.getXAxis().setPosition(XAxis.XAxisPosition.BOTTOM);
        mLineChart.getXAxis().setTextColor(Color.WHITE);
        mLineChart.getXAxis().setLabelCount(COUNT_LABEL[mCurrentType], true);
        mLineChart.getXAxis().setValueFormatter(new IAxisValueFormatter() {
            @Override
            public String getFormattedValue(float value, AxisBase axis) {
                try {
                    Calendar calendar1 = Calendar.getInstance();
                    calendar1.add(DATE_UNIT[mCurrentType], (int) (COUNT_LABEL[mCurrentType] - value) * -1);
                    return Utils.convertToString(calendar1.getTime(), FORMAT_LABEL[mCurrentType]);
                } catch (Exception e) {
                    return "";
                }
            }
        });

        mLineChart.setDragEnabled(false);
        mLineChart.setScaleEnabled(false);
        mLineChart.setDescription(null);
        mLineChart.getLegend().setPosition(Legend.LegendPosition.BELOW_CHART_CENTER);
        mLineChart.getLegend().setTextColor(Color.WHITE);
        mLineChart.invalidate();

        String unit = "%";
        if (mPosition == 0) {
            unit = Utils.getUnitWeight(mProfile.getWeight_unit());
        }
        if (mPosition == 6) {
            unit = "Kg";
        }
        if (mPosition == 7) {
            unit = "Kcal";
        }

        EntryTimeAdapter adapter = new EntryTimeAdapter(mEntryTimes, FORMAT_TIME[mCurrentType], FORMAT_TIME_RESPONSE[mCurrentType],
                unit);
        RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(getContext());
        mRecyclerView.setLayoutManager(layoutManager);
        mRecyclerView.setAdapter(adapter);
        mRecyclerView.setNestedScrollingEnabled(false);
        mAvg.setText(getAvg() + "");
        if (mProfile != null) {
            mGoal.setText(mProfile.getGoalWeight(mProfile.getWeight_unit()) + "");
            mGoalUnit.setText(String.format(getString(R.string.goal_s), Utils.getUnitWeight(mProfile.getWeight_unit())));
            if (mPosition == 0) {
                mAvgUnit.setText(String.format(getString(R.string.weight_s), Utils.getUnitWeight(mProfile.getWeight_unit())));
            } else {
                mAvgUnit.setText(getString(Utils.getIdEntry(mPosition)) + " (%)");
            }
        }
        if (mPosition > 0) {
            mAvg.setTextColor(getResources().getColor(getIdColor(mPosition)));
            mAvgUnit.setTextColor(getResources().getColor(getIdColor(mPosition)));
        }

    }

    public class MyValueFormatter implements IAxisValueFormatter {
        @Override
        public String getFormattedValue(float value, AxisBase axis) {
            String unit = "";
            if (mPosition == 0 && mProfile != null) {
                unit = Utils.getUnitWeight(mProfile.getWeight_unit());
            }
            return Utils.formatFloat(value) + unit;
        }
    }

    private void setTab(int tab) {
        if (tab == mCurrentType) {
            return;
        }
        mCurrentType = tab;
        for (int i = 0; i < mTabLine.length; i++) {
            if (i == tab) {
                mTabText[i].setTextColor(getResources().getColor(R.color.bg_select_tall_btn));
                mTabLine[i].setVisibility(View.VISIBLE);
            } else {
                mTabText[i].setTextColor(getResources().getColor(R.color.text_color_reminder));
                mTabLine[i].setVisibility(View.GONE);
            }
        }
        if (mCurrentType == 0) {
            mStartDateSelect = mStartDateDay;
            mLabelTime.setText(Utils.convertToString(mStartDateDay, Utils.DATE_FORMAT_MMM_DD_YYYY)
                    + " - " + Utils.convertToString(mEndDate, Utils.DATE_FORMAT_MMM_DD_YYYY));
            mLabelTimeTitle.setText(getString(R.string.last_day_7) + " - " + getString(Utils.getIdEntry(mPosition)));
        } else if (mCurrentType == 1) {
            mStartDateSelect = mStartDate4Week;
            mLabelTime.setText(Utils.convertToString(mStartDate4Week, FORMAT_TIME[mCurrentType])
                    + " - " + Utils.convertToString(mEndDate, FORMAT_TIME[mCurrentType]));
            mLabelTimeTitle.setText(getString(R.string.last_week_4) + " - " + getString(Utils.getIdEntry(mPosition)));
        } else if (mCurrentType == 2) {
            mStartDateSelect = mStartDate12Month;
            mLabelTime.setText(Utils.convertToString(mStartDate12Month, "MMM yyyy")
                    + " - " + Utils.convertToString(mEndDate, "MMM yyyy"));
            mLabelTimeTitle.setText(getString(R.string.last_month_12) + " - " + getString(Utils.getIdEntry(mPosition)));
        }
        getData();
    }

    public float getAvg() {
        if (mEntryTimes == null || mEntryTimes.size() == 0) {
            return 0;
        }
        float avg = 0;
        for (EntryTime entryTime : mEntryTimes) {
            String unit = "%";
            if (mPosition == 0) {
                unit = Utils.getUnitWeight(mProfile.getWeight_unit());
            }
            if (mPosition == 6) {
                unit = "Kg";
            }
            if (mPosition == 7) {
                unit = "Kcal";
            }
            avg += entryTime.getValue(unit);
        }
        return Utils.formatFloat(avg / mEntryTimes.size());
    }

    public int convertDateToInt(String time) {
        Date date = Utils.convertToDate(time, FORMAT_TIME_RESPONSE[mCurrentType]);
        return convertDateToInt(date);
    }

    public int convertDateToInt(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        int i = calendar.get(Calendar.YEAR);
        i = i * 365 + calendar.get(Calendar.MONTH) * 30 + calendar.get(Calendar.DAY_OF_MONTH);
        return i;
    }

    public String convertDateToLabel(float f) {
        int time = (int) f;
        int year = time / 365;
        int month = time % 365;
        int day = month % 30;
        month = month / 30;
        Calendar calendar = Calendar.getInstance();
        calendar.set(year, month, day);
        return Utils.convertToString(calendar.getTime(), FORMAT_LABEL[mCurrentType]);
    }

    private int getIdColor(int pos) {
        switch (pos) {
            case 0:
                return R.color.bg_select_tall_btn;
            case 1:
                return R.color.text_color_bmi;
            case 2:
                return R.color.text_color_body_fat;
            case 3:
                return R.color.text_color_muscle;
            case 4:
                return R.color.text_color_water;
            case 5:
                return R.color.text_color_visceral_fat;
            case 6:
                return R.color.text_color_bone_mass;
            case 7:
                return R.color.text_color_bmr;
        }
        return 0;
    }
}
